home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 145
/
Gekkan Dennou Club - 2000.6 Vol. 145 (Japan).7z
/
Gekkan Dennou Club - 2000.6 Vol. 145 (Japan) (Track 1).bin
/
html
/
docs
/
asm
/
optime.txt
< prev
Wrap
Text File
|
2000-05-08
|
8KB
|
304 lines
;----------------------------------------------------------------
;内容
; サブルーチンの所要時間を測るためのルーチンです。
; スーパーバイザモードで呼び出して下さい。
; Timer-CとTimer-Dを使用するので,Timer-Dが使用中の場合は停止しておいて下さい。
;
;呼び出し手順
; move.l #param,-(sp) ;初期化ルーチンのパラメータ(ループ回数など)
; pea.l tini ;後始末ルーチン(不要ならば0)
; pea.l init ;初期化ルーチン(不要ならば0)
; pea.l main ;計測するルーチン
; jsr optime ;d0.l=計測するルーチンの所要時間(μs単位で12799まで)
; lea.l (16,sp),sp
;
;リンク時の注意事項
; lk -e16のように16バイトアラインメントでリンクして下さい。
;
;各ルーチンの設定
; 各ルーチンはスーパーバイザモードで呼ばれます。
; sspは復帰アドレスをプッシュする前に16バイト単位にアラインメントされています。
; 初期化ルーチンから後始末ルーチンまでd0-d7/a0-a5を自由に使って構いません。
; a6レジスタはサブルーチンのアドレスとして使用していますが,破壊しても構いません。
; 初期化ルーチンでレジスタに設定した値はa6を除いてそのまま計測するルーチンに渡されます。
; 例えば,初期化ルーチンでカウンタを初期化し,計測ルーチンでループを開始できます。
;
;各ルーチンの呼び出し順序
; 初期化ルーチン→計測するルーチン→後始末ルーチンの順序で,2回呼び出します。
; 1回目は各ルーチンを命令キャッシュに乗せるための準備です。
; 2回目の,計測するルーチンの所要時間をμs単位で計測します。
; なお,所要時間には呼び出しと復帰の時間が含まれています。
; 一連の呼び出しの間,割り込みは止められています。
;
;計測結果
; 計測結果はd0.lにμs単位で格納されます。
; 最大計測時間は12799μsです。これを超えると正確に計測できません。
; 50MHzのとき1clock=0.02μsですから,適当な回数だけループさせるなどして下さい。
;----------------------------------------------------------------
.cpu 68000
;----------------------------------------------------------------
;MFPのアドレス
GPIPDR equ $00E88001
AER equ $00E88003
DDR equ $00E88005
IERA equ $00E88007
IERB equ $00E88009
IPRA equ $00E8800B
IPRB equ $00E8800D
ISRA equ $00E8800F
ISRB equ $00E88011
IMRA equ $00E88013
IMRB equ $00E88015
VECTR equ $00E88017
TACR equ $00E88019
TBCR equ $00E8801B
TCDCR equ $00E8801D
TADR equ $00E8801F
TBDR equ $00E88021
TCDR equ $00E88023
TDDR equ $00E88025
SCR equ $00E88027
UCR equ $00E88029
RSR equ $00E8802B
TSR equ $00E8802D
UDR equ $00E8802F
;----------------------------------------------------------------
;ベクタアドレス
TIMER_D_VECTOR equ $0110
;----------------------------------------------------------------
;間接サブルーチンコール(000用)
jsrr .macro dst
.local next
move.l dst,-(sp) ;dspがspを参照している場合があるので最初にプッシュする
move.l (sp),-(sp)
move.l #next,(4,sp)
rts
next:
.endm
;----------------------------------------------------------------
;パラメータの内容
.offset 0
p_pc .ds.l 1 ;復帰アドレス
p_main: .ds.l 1 ;計測するルーチン
p_init: .ds.l 1 ;初期化ルーチン
p_tini: .ds.l 1 ;後始末ルーチン
p_param: .ds.l 1 ;初期化ルーチンのパラメータ(ループ回数など)
.text
;----------------------------------------------------------------
;スタックの内容
.offset 0
v_main: .ds.l 1 ;計測するルーチン
v_init: .ds.l 1 ;初期化ルーチン
v_tini: .ds.l 1 ;後始末ルーチン
v_param: .ds.l 1 ;初期化ルーチンのパラメータ(ループ回数など)
v_ssp: .ds.l 1 ;元のスタックポインタ(この位置+16以上)
v_test: .ds.b 1 ;0=本番,-1=リハーサル
v_tcdcr: .ds.b 1 ;TCDCRのワーク
v_imrb: .ds.b 1 ;IMRBのワーク
v_ierb: .ds.b 1 ;IERBのワーク
.align 16
v_size:
.text
;----------------------------------------------------------------
;計測ルーチン
; スーパーバイザモードで呼び出すこと
;<(4,sp).l:計測するルーチン
;<(8,sp).l:初期化ルーチン(不要ならば0)
;<(12,sp).l:後始末ルーチン(不要ならば0)
;>d0.l:所要時間(単位はμs,0~12799),-1=Timer-Dが使用中
;----------------------------------------------------------------
.even
_optime::
movem.l d1-d7/a0-a6,-(sp) ;ここではa6も必要
lea.l (4*14,sp),a6 ;pcのアドレス
;Timer-Dの使用状態の確認
btst.b #4,IERB
beq @f ;Timer-Dは使用されていない
movea.l $1C20.w,a0 ;Humanの先頭
move.l (8,a0),d0 ;Humanの末尾
cmp.l TIMER_D_VECTOR,d0
bcc @f ;Timer-DはHumanが使用中
moveq.l #-1,d0 ;Timer-DはHuman以外が使用中
bra 99f
@@:
;割り込み禁止
move.w sr,-(sp)
ori.w #$0700,sr
;ワークの確保とアラインメント
move.l sp,d0
and.l #$0000000F,d0
neg.l d0
move.l sp,(-v_size+v_ssp,sp,d0.l) ;割り込みを止めてあるので,
lea.l (-v_size,sp,d0.l),sp ;この間に割り込みなどでスタックが壊れることはない
;各ルーチンのアドレスをセット
move.l (p_main,a6),(v_main,sp) ;計測するルーチン
lea.l (dummy_routine,pc),a0
move.l (p_init,a6),d0
beq @f
movea.l d0,a0
@@: move.l a0,(v_init,sp) ;初期化ルーチン
lea.l (dummy_routine,pc),a0
move.l (p_tini,a6),d0
beq @f
movea.l d0,a0
@@: move.l a0,(v_tini,sp) ;後始末ルーチン
move.l (p_param,a6),(v_param,sp) ;初期化ルーチンのパラメータ
;タイマ設定
move.b IERB,(v_ierb,sp)
move.b IMRB,(v_imrb,sp)
move.b TCDCR,(v_tcdcr,sp)
andi.b #%11001111,IERB ;Timer-C/D割り込み停止
andi.b #%11001111,IMRB ;Timer-C/D割り込み禁止
sf.b TCDCR ;Timer-C/Dカウント停止
@@: tst.b TCDCR ;完全に停止するまで待つ
bne @b
;000~010と020~060で処理を分ける
@@: moveq.l #1,d0
.cpu 68020
and.b (@b-1,pc,d0.l*2),d0
.cpu 68000
bne measure_020
;000~010用の計測ルーチン
measure_000:
st.b (v_test,sp) ;リハーサル
retry_000:
movea.l (v_init,sp),a6
move.l (v_param,sp),-(sp)
jsr (a6) ;初期化ルーチンを呼ぶ
addq.l #4,sp
sf.b TCDR ;Timer-Cカウンタクリア
@@: tst.b TCDR ;カウンタが更新されるまで待つ
bne @b
sf.b TDDR ;Timer-Dカウンタクリア
@@: tst.b TDDR ;カウンタが更新されるまで待つ
bne @b
movea.l (v_main,sp),a6 ;計測するルーチン
;カウント開始
; TCCR TDCR
move.b #%0111_0001,TCDCR ;Timer-C/Dカウント開始
; Timer-Cは1/200プリスケール(50μs)
; Timer-Dは1/4プリスケール(1μs)
;計測するルーチンを呼び出す
jsr (a6)
;カウント停止
sf.b TCDCR ;Timer-C/Dカウント停止
@@: tst.b TCDCR ;完全に停止するまで待つ
bne @b
movea.l (v_tini,sp),a6
jsr (a6) ;後始末ルーチンを呼ぶ
not.b (v_test,sp)
beq retry_000
bra measure_done
;020~060用の計測ルーチン
.cpu 68020
measure_020:
st.b (v_test,sp) ;リハーサル
retry_020:
movea.l (v_init,sp),a6
move.l (v_param,sp),-(sp)
jsr (a6) ;初期化ルーチンを呼ぶ
addq.l #4,sp
sf.b TCDR ;Timer-Cカウンタクリア
@@: tst.b TCDR ;カウンタが更新されるまで待つ
bne @b
sf.b TDDR ;Timer-Dカウンタクリア
@@: tst.b TDDR ;カウンタが更新されるまで待つ
bne @b
movea.l (v_main,sp),a6 ;計測するルーチン
bra @f
.align 16
.ds.w 16-3
@@:
;カウント開始
; TCCR TDCR
move.b #%0111_0001,TCDCR ;Timer-C/Dカウント開始
; Timer-Cは1/200プリスケール(50μs)
; Timer-Dは1/4プリスケール(1μs)
;計測するルーチンを呼び出す
jsr (a6)
;カウント停止
sf.b TCDCR ;Timer-C/Dカウント停止
@@: tst.b TCDCR ;完全に停止するまで待つ
bne @b
movea.l (v_tini,sp),a6
jsr (a6) ;後始末ルーチンを呼ぶ
not.b (v_test,sp)
beq retry_020
.cpu 68000
;計測終わり
measure_done:
;タイマ取得
moveq.l #0,d0
moveq.l #0,d1
sub.b TCDR,d0 ;Timer-Cカウント数
sub.b TDDR,d1 ;Timer-Dカウント数(オーバーフローあり)
;タイマ後始末
move.b #200,TCDR ;Timer-Cカウンタ復元
move.b #20,TDDR ;Timer-Dカウンタ復元
move.b (v_imrb,sp),IMRB
move.b (v_ierb,sp),IERB
move.b (v_tcdcr,sp),TCDCR
;ワークの開放
movea.l (v_ssp,sp),sp ;元のスタックポインタ
;割り込み許可
move.w (sp)+,sr
;カウンタを合成する
mulu.w #50,d0
cmp.b d1,d0
bls @f
add.w #$0100,d0
@@: move.b d1,d0
subq.w #1,d0
99: tst.l d0
movem.l (sp)+,d1-d7/a0-a6
rts
dummy_routine:
rts